#include <cstdio>
#include <cstdint>
#include <cerrno>
#include <thread>
#include <chrono>
#include <cmath>
#include <algorithm>
#include <atomic>
#include <vector>
#include <iterator>
#include <string>

#include "simple/support/misc.hpp"
#include "simple/musical/initializer.h"
#include "simple/musical/device.h"

using namespace simple::musical;
using namespace std::literals;

int main(int argc, const char** argv) try
{
	switch(argc)
	{
		case 0: std::puts("command not specified??");
		case 1: std::puts("file not specified");
		case 2: std::puts("format not specified");
		case 3: std::puts("channels not specified");
		case 4: std::puts("frequency not specified");
		// case 5: std::puts("layout not specified"); planar vs interlaced // TODO
			return -1;
	}

	initializer init;

	auto file = fopen(argv[1], "r");
    std::fseek(file, 0, SEEK_END);
    const std::size_t filesize = std::ftell(file);
    std::vector<std::uint8_t> input(filesize);
	std::fseek(file, 0, SEEK_SET);
    std::fread(input.data(), 1, input.size(), file);
	fclose(file);


	std::atomic<bool> done = false;
	device_with_callback player
	(
		basic_device_parameters{ spec{
			simple::support::ston<int>(argv[4]),
			format_from_c_str(argv[2]),
			static_cast<spec::channels>(simple::support::ston<std::uint8_t>(argv[3]))
		}},
		[&done, &input, i = input.begin()](auto& device, auto buffer) mutable
		{
			const int remaining = input.end() - i;
			const int buffer_size = buffer.end() - buffer.begin();
			const int size = std::min<int>(remaining, buffer_size);
			const int extra = buffer_size - size;

			std::copy(i, i + size, buffer.begin());
			std::fill_n(buffer.begin() + size, extra, device.silence());

			i += size;
			if(i == input.end())
				done = true;
		}
	);

	player.play();

	while(!done)
		std::this_thread::sleep_for(50ms);

	return 0;
}
catch(...)
{
	if(errno)
		std::perror("ERROR");

	const char* sdl_error = SDL_GetError();
	if(*sdl_error)
		std::puts(sdl_error);

	throw;
}
